﻿Public Class Characters
    Inherits List(Of Character)

    Public Event SpeedChanged(ByVal item As Character, ByVal newspeed As Double)
    Public Event EnduranceChanged(ByVal item As Character, ByVal newendurance As Integer)
    Public Event RecoveryChanged(ByVal item As Character, ByVal newrecovery As Integer)
    Public Event BodyChanged(ByVal item As Character, ByVal newbody As Integer)
    Public Event StunChanged(ByVal item As Character, ByVal newstun As Integer)
    Public Event CharacterAdded(ByVal item As Character)
    Public Event CharacterRemoved(ByVal item As Character)

    Public Overloads Sub Add(ByVal item As Character)
        AddHandler item.BodyChanged, AddressOf OnItemBodyChanged
        AddHandler item.EnduranceChanged, AddressOf OnItemEnduranceChanged
        AddHandler item.RecoveryChanged, AddressOf OnItemRecoveryChanged
        AddHandler item.SpeedChanged, AddressOf OnItemSpeedChanged
        AddHandler item.StunChanged, AddressOf OnItemStunChanged
        MyBase.Add(item)
        Me.Sort(AddressOf InitiativeOrder)
        RaiseEvent CharacterAdded(item)
    End Sub

    Public Overloads Sub AddRange(ByVal items As Characters)
        For Each Item As Character In items
            Me.Add(Item)
        Next
    End Sub

    Public Overloads Sub Remove(ByVal item As Character)
        RemoveHandler item.BodyChanged, AddressOf OnItemBodyChanged
        RemoveHandler item.EnduranceChanged, AddressOf OnItemEnduranceChanged
        RemoveHandler item.RecoveryChanged, AddressOf OnItemRecoveryChanged
        RemoveHandler item.SpeedChanged, AddressOf OnItemSpeedChanged
        RemoveHandler item.StunChanged, AddressOf OnItemStunChanged
        MyBase.Remove(item)
        RaiseEvent CharacterRemoved(item)
    End Sub

    Public Overloads Sub Clear()
        For Each Item As Character In Me
            Me.Remove(Item)
        Next
    End Sub

    Public Overloads Function Find(ByVal name As String) As Character
        For Each c As Character In Me
            If c.Name = name Then
                Return c
            End If
        Next
        Return Nothing
    End Function

    Public Sub Edit(ByVal original As Character, ByVal item As Character)
        If Me.Contains(original) Then
            Dim c As Character = Me.Find(original.Name)
            Me.Remove(c)
            Me.Add(item)
        End If
        If original.CurrentBody <> item.CurrentBody Then
            RaiseEvent BodyChanged(item, item.CurrentBody)
        End If
        If original.CurrentStun <> item.CurrentStun Then
            RaiseEvent StunChanged(item, item.CurrentStun)
        End If
        If original.CurrentEndurance <> item.CurrentEndurance Then
            RaiseEvent EnduranceChanged(item, item.CurrentEndurance)
        End If
    End Sub

    Private Sub OnItemBodyChanged(ByVal item As Character, ByVal newbody As Integer)
        RaiseEvent BodyChanged(item, newbody)
    End Sub

    Private Sub OnItemEnduranceChanged(ByVal item As Character, ByVal newendurance As Integer)
        RaiseEvent EnduranceChanged(item, newendurance)
    End Sub

    Private Sub OnItemRecoveryChanged(ByVal item As Character, ByVal newrecovery As Integer)
        RaiseEvent RecoveryChanged(item, newrecovery)
    End Sub

    Private Sub OnItemSpeedChanged(ByVal item As Character, ByVal newspeed As Double)
        RaiseEvent SpeedChanged(item, newspeed)
    End Sub

    Private Sub OnItemStunChanged(ByVal item As Character, ByVal newstun As Integer)
        RaiseEvent StunChanged(item, newstun)
    End Sub

    Private Function InitiativeOrder(ByVal x As Character, ByVal y As Character) As Integer
        If x Is Nothing Then
            If y Is Nothing Then
                Return 0
            Else
                Return 1
            End If
        Else
            If y Is Nothing Then
                Return -1
            Else
                'compare dexterity
                If x.Dexterity > y.Dexterity Then
                    Return -1
                ElseIf x.Dexterity = y.Dexterity Then
                    'compare npc flags
                    If Not x.NPC And y.NPC Then
                        Return -1
                    ElseIf x.NPC And Not y.NPC Then
                        Return 1
                    Else
                        'compare names for alpha order
                        Return String.Compare(x.Name, y.Name)
                    End If
                End If
            End If
        End If
    End Function
End Class
